Functions, Arrow Functions, and Callback Functions in JavaScript for React Native
Course: React Native Training
Topic: Functions, Arrow Functions, and Callback Functions
Course Link: React Native Training at JustAcademy
Demo Link: Register for a Free Course Demo
Website: JustAcademy
1. Introduction to Functions in JavaScript
Functions are one of the most important concepts in JavaScript and React Native development. A function is a reusable block of code designed to perform a particular task. Instead of writing the same instructions repeatedly, developers can place the instructions inside a function and execute them whenever required.
In React Native, functions are used to handle button presses, validate forms, process user input, calculate values, fetch data from APIs, update state, render lists, and manage application behavior.
1.1 Why Are Functions Important?
- Code reusability: Write logic once and use it multiple times.
- Modularity: Divide a large application into smaller, manageable parts.
- Readability: Give meaningful names to operations and make code easier to understand.
- Maintainability: Update logic in one place instead of modifying repeated code.
- Event handling: Respond to user actions such as button presses and text input.
- Asynchronous operations: Process API requests and other tasks that take time.
- Component behavior: Define reusable logic inside React Native functional components.
1.2 Example Without a Function
const price1 = 100;
const tax1 = 10;
const total1 = price1 + tax1;
const price2 = 200;
const tax2 = 20;
const total2 = price2 + tax2;
console.log(total1);
console.log(total2);
The calculation is repeated for different values. If the calculation becomes more complex, repeating the same logic can make the program harder to maintain.
1.3 Example Using a Function
function calculateTotal(price, tax) {
return price + tax;
}
console.log(calculateTotal(100, 10));
console.log(calculateTotal(200, 20));
The function can now be reused with different arguments. This approach reduces duplication and makes the program easier to maintain.
2. Learning Objectives
After completing this topic, learners should be able to:
- Understand the purpose and structure of JavaScript functions.
- Declare and call functions correctly.
- Differentiate parameters from arguments.
- Use return statements to produce results.
- Understand function expressions and anonymous functions.
- Create and use arrow functions.
- Understand the differences between traditional functions and arrow functions.
- Explain callback functions and higher-order functions.
- Use callbacks with array methods such as map(), filter(), and forEach().
- Handle React Native events with functions and callbacks.
- Understand asynchronous callbacks and basic error handling.
- Apply functions in a small React Native application.
3. Understanding Function Syntax
A standard JavaScript function declaration uses the function keyword, followed by a function name, parentheses, and a code block enclosed in curly braces.
3.1 Basic Syntax
function functionName(parameters) {
// Code to execute
return result;
}
Parts of a function:
function: Keyword used to declare a traditional function.
functionName: The name used to identify and call the function.
parameters: Variables that receive input values.
{ }: The function body containing instructions.
return: An optional statement that sends a result back to the caller.
3.2 Creating and Calling a Function
function greetUser() {
console.log("Welcome to React Native!");
}
greetUser();
Output:
Welcome to React Native!
Declaring a function does not automatically execute its body. The function must be called, as shown by greetUser().
3.3 Calling a Function Multiple Times
function showMessage() {
console.log("Learning JavaScript functions");
}
showMessage();
showMessage();
showMessage();
The same function executes three times. Each call runs the statements inside its body.
3.4 Functions with Parameters
Parameters allow functions to receive values and work with different inputs.
function greet(name) {
console.log("Hello, " + name);
}
greet("Aarav");
greet("Priya");
Output:
Hello, Aarav
Hello, Priya
Here, name is a parameter. The values "Aarav" and "Priya" are arguments passed to the function.
4. Parameters and Arguments
Parameters and arguments are related concepts, but they have different roles. Parameters are variables listed in a function definition. Arguments are the actual values supplied when calling that function.
4.1 Example
function multiply(a, b) {
return a * b;
}
const result = multiply(5, 4);
console.log(result);
Output:
20
a and b are parameters.
5 and 4 are arguments.
a * b is the calculation.
return sends the calculated value back to the caller.
4.2 Multiple Parameters
function calculateArea(length, width) {
return length * width;
}
console.log(calculateArea(10, 5));
console.log(calculateArea(8, 3));
Output:
50
24
4.3 Default Parameters
Default parameters provide fallback values when an argument is omitted or explicitly supplied as undefined.
function greet(name = "Guest") {
return `Welcome, ${name}!`;
}
console.log(greet("Riya"));
console.log(greet());
Output:
Welcome, Riya!
Welcome, Guest!
Default parameters are useful when an optional value has a sensible fallback.
4.4 Rest Parameters
Rest parameters allow a function to receive any number of arguments as an array.
function calculateSum(...numbers) {
return numbers.reduce((total, number) => total + number, 0);
}
console.log(calculateSum(10, 20));
console.log(calculateSum(5, 10, 15, 20));
Output:
30
50
The rest parameter ...numbers collects all remaining arguments into an array. Rest parameters must be the final parameter in a function's parameter list.
5. Return Statements in Functions
The return statement ends the current function execution and optionally provides a value to the caller. A returned value can be stored in a variable, displayed in the interface, or passed to another function.
5.1 Function That Returns a Value
function add(a, b) {
return a + b;
}
const result = add(10, 15);
console.log(result);
Output:
25
5.2 Function Without an Explicit Return Value
function showWelcome() {
console.log("Welcome!");
}
const result = showWelcome();
console.log(result);
Output:
Welcome!
undefined
A function without an explicit return value returns undefined.
5.3 Returning Early
A function can return before reaching its final statement. This is useful for validation and handling invalid input.
function checkAge(age) {
if (age < 18) {
return "Not eligible";
}
return "Eligible";
}
console.log(checkAge(16));
console.log(checkAge(21));
Output:
Not eligible
Eligible
5.4 Important Difference Between return and console.log()
return sends a value back to the code that called the function.
console.log() prints a value in the development console.
- A logged value is not automatically returned by the function.
function firstExample() {
return 10;
}
function secondExample() {
console.log(10);
}
const first = firstExample();
const second = secondExample();
console.log(first); // 10
console.log(second); // undefined
6. Types of Functions in JavaScript
JavaScript supports several ways to define and use functions. The best choice depends on how the function needs to behave and how it will be used.
6.1 Function Declaration
function subtract(a, b) {
return a - b;
}
console.log(subtract(10, 4));
Function declarations are generally initialized during the scope's instantiation process, so they can usually be called before their declaration appears in the code.
6.2 Function Expression
A function expression creates a function and assigns it to a variable.
const divide = function (a, b) {
return a / b;
};
console.log(divide(20, 4));
Because this example uses const, the variable cannot be accessed before its declaration is initialized.
6.3 Anonymous Function
An anonymous function is a function without its own explicit name. Anonymous functions are often used in function expressions and callbacks.
const sayHello = function () {
console.log("Hello!");
};
sayHello();
6.4 Named Function Expression
const factorial = function calculateFactorial(number) {
if (number <= 1) {
return 1;
}
return number * calculateFactorial(number - 1);
};
console.log(factorial(5));
The internal name calculateFactorial can be useful for recursion and debugging.
6.5 Immediately Invoked Function Expression (IIFE)
An IIFE is a function expression that executes immediately after it is defined.
(function () {
console.log("This function runs immediately.");
})();
IIFEs are less common in modern React Native application code because modules, block scope, and functions declared within components often provide clearer alternatives.
6.6 Recursive Function
A recursive function calls itself to solve a problem. It needs a base case to prevent infinite recursion.
function countdown(number) {
if (number <= 0) {
console.log("Finished");
return;
}
console.log(number);
countdown(number - 1);
}
countdown(3);
Output:
3
2
1
Finished
7. Arrow Functions in JavaScript
Arrow functions provide a concise syntax for creating function expressions. They were introduced in ECMAScript 2015 (ES6) and are widely used in modern JavaScript and React Native projects.
An arrow function uses the => symbol, commonly called the arrow operator.
7.1 Basic Arrow Function Syntax
const functionName = (parameters) => {
// Function body
return result;
};
7.2 Traditional Function and Arrow Function Comparison
// Traditional function
function add(a, b) {
return a + b;
}
// Arrow function
const addArrow = (a, b) => {
return a + b;
};
console.log(add(5, 3));
console.log(addArrow(5, 3));
Both functions return the sum of their two arguments.
7.3 Arrow Function with One Parameter
Parentheses around a single parameter can be omitted, although keeping them is also valid.
const square = number => {
return number * number;
};
console.log(square(6));
Output:
36
7.4 Arrow Function with No Parameters
When there are no parameters, empty parentheses are required.
const showMessage = () => {
console.log("Hello from React Native!");
};
showMessage();
7.5 Implicit Return
If an arrow function contains a single expression, the expression's value can be returned without writing the return keyword or a function body.
const add = (a, b) => a + b;
const double = number => number * 2;
console.log(add(10, 20));
console.log(double(7));
Output:
30
14
7.6 Returning an Object from an Arrow Function
When implicitly returning an object literal, wrap the object in parentheses. Otherwise, the curly braces may be interpreted as the function body.
const createUser = (name, age) => ({
name: name,
age: age
});
console.log(createUser("Aman", 25));
Output:
{ name: 'Aman', age: 25 }
7.7 Multiline Arrow Function
Use curly braces when the function needs multiple statements. Include an explicit return statement when a value must be returned.
const calculateDiscount = (price, percentage) => {
const discount = price * percentage / 100;
const finalPrice = price - discount;
return finalPrice;
};
console.log(calculateDiscount(1000, 10));
Output:
900
8. Traditional Functions vs Arrow Functions
| Feature |
Traditional Function |
Arrow Function |
| Syntax |
Uses the function keyword |
Uses the => operator |
| Length |
Can require more code |
Often more concise |
| Own this |
Depends on how the function is called |
Uses this from its surrounding lexical scope |
| Own arguments object |
Available in ordinary non-arrow functions |
Not available as its own arguments object |
| Constructor |
Some traditional functions can be called with new |
Cannot be used as constructors |
| Implicit return |
Not supported in ordinary function bodies |
Supported for concise expression bodies |
| Common usage |
Named utilities, methods, constructors, and special cases |
Callbacks, concise utilities, and React event handlers |
8.1 Understanding this in Traditional Functions
In an ordinary function, the value of this depends on how the function is called. For example, a method call usually binds this to the object before the dot.
const user = {
name: "Rohan",
greet: function () {
return `Hello, ${this.name}`;
}
};
console.log(user.greet());
Output:
Hello, Rohan
8.2 Understanding Lexical this in Arrow Functions
Arrow functions do not create their own this. They use the value from the surrounding lexical scope. This is useful in many callbacks, but an arrow function should not be used when a method needs its own dynamically determined this.
const user = {
name: "Rohan",
greet() {
return () => {
return `Hello, ${this.name}`;
};
}
};
const greeting = user.greet();
console.log(greeting());
Output:
Hello, Rohan
8.3 When Should You Use Arrow Functions?
- For short calculations and utility functions.
- For callbacks passed to array methods.
- For event handlers in React Native components.
- For callbacks that should retain the surrounding lexical
this.
- For inline functions where concise syntax improves readability.
8.4 When Might a Traditional Function Be Better?
- When you need a function's own
this behavior.
- When defining a constructor function that supports
new.
- When you need an ordinary function's own
arguments object.
- When a named function declaration improves clarity or supports calling the function before its declaration.
9. Scope and Closures in Functions
Scope determines where a variable can be accessed. Understanding scope is important when working with callbacks, event handlers, and React Native state.
9.1 Global Scope
A variable declared at the top level of a module can generally be accessed by functions defined within that module, subject to the module's scope.
const appName = "My React Native App";
function showAppName() {
console.log(appName);
}
showAppName();
9.2 Function Scope
Variables declared with let or const inside a function are accessible within that function and its nested scopes, but not from outside the function.
function displayMessage() {
const message = "Hello!";
console.log(message);
}
displayMessage();
// console.log(message); // ReferenceError
9.3 Block Scope
Variables declared using let and const are limited to the block in which they are declared.
if (true) {
const status = "Active";
console.log(status);
}
// console.log(status); // ReferenceError
9.4 Lexical Scope and Closures
A nested function can access variables from the scope where it was created. When a function retains access to its surrounding lexical environment after the outer function has finished, this is called a closure.
function createCounter() {
let count = 0;
return function () {
count += 1;
return count;
};
}
const counter = createCounter();
console.log(counter());
console.log(counter());
console.log(counter());
Output:
1
2
3
Closures are useful for preserving values between function calls. In React, callbacks can capture values from the render in which they were created, so developers should understand how state and dependencies affect callback behavior.
10. Callback Functions
A callback is a function passed to another function as an argument so that the receiving function can invoke it. Callbacks allow developers to customize what happens after an operation, when an event occurs, or while processing data.
Callbacks are commonly used in JavaScript array methods, React Native event handlers, timers, and asynchronous operations.
10.1 Basic Callback Example
function greet(name, callback) {
console.log("Hello, " + name);
callback();
}
function showMessage() {
console.log("Welcome to JavaScript!");
}
greet("Aarav", showMessage);
Output:
Hello, Aarav
Welcome to JavaScript!
The function showMessage is passed as a value, without parentheses. The receiving function calls it using callback().
10.2 Passing an Anonymous Function as a Callback
function processTask(callback) {
console.log("Processing task...");
callback();
}
processTask(function () {
console.log("Task completed.");
});
10.3 Passing an Arrow Function as a Callback
function calculate(a, b, callback) {
return callback(a, b);
}
const result = calculate(10, 5, (x, y) => x + y);
console.log(result);
Output:
15
10.4 Callback with Parameters
function sendNotification(message, callback) {
console.log("Notification: " + message);
callback(message);
}
sendNotification("Your order has shipped.", message => {
console.log("Logged message: " + message);
});
The receiving function can pass data to the callback when it invokes it.
10.5 Why Are Callbacks Useful?
- They allow one function to define what happens after another operation.
- They support reusable and configurable behavior.
- They help process items in arrays.
- They are used to handle UI events in React Native.
- They can respond to the completion of asynchronous work.
- They allow functions to communicate results without hardcoding every possible action.
11. Synchronous and Asynchronous Callbacks
11.1 Synchronous Callback
A synchronous callback executes during the current operation, before that operation finishes returning control to its caller.
function calculate(number, callback) {
const result = number * 2;
callback(result);
}
calculate(5, result => {
console.log("Result:", result);
});
console.log("Finished");
Output:
Result: 10
Finished
11.2 Asynchronous Callback
An asynchronous callback executes later, after a timer, event, or other asynchronous operation reaches the appropriate point.
console.log("Start");
setTimeout(() => {
console.log("Timer callback executed");
}, 1000);
console.log("End");
The typical output order is:
Start
End
Timer callback executed
The timer schedules the callback to run later. The main JavaScript execution continues without waiting for the timer to finish.
11.3 Callback Timing Matters
A callback does not automatically mean that an operation is asynchronous. The function receiving the callback decides when and how often to invoke it. Array methods such as map() normally invoke their callbacks synchronously, while event handlers and timers may execute at a later time.
12. Callback Functions with Array Methods
JavaScript array methods accept callback functions to process array items. These methods are frequently used to display lists, transform data received from APIs, and filter information in React Native applications.
12.1 map()
The map() method creates a new array by applying a callback to each element of the original array.
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(number => number * 2);
console.log(doubled);
Output:
[2, 4, 6, 8]
Use map() when you want to transform every item into a corresponding value.
12.2 filter()
The filter() method creates a new array containing the elements for which the callback returns a truthy value.
const numbers = [10, 15, 20, 25, 30];
const filtered = numbers.filter(number => number > 20);
console.log(filtered);
Output:
[25, 30]
12.3 forEach()
The forEach() method calls a callback for each array element. It is useful when you need to perform an action for every item and do not need a new array returned by the method.
const names = ["Aarav", "Priya", "Rohan"];
names.forEach(name => {
console.log(name);
});
Output:
Aarav
Priya
Rohan
forEach() returns undefined, so it should not be used when you need the transformed array.
12.4 find()
The find() method returns the first element for which the callback returns a truthy value. If no element matches, it returns undefined.
const users = [
{ id: 1, name: "Aarav" },
{ id: 2, name: "Priya" },
{ id: 3, name: "Rohan" }
];
const user = users.find(item => item.id === 2);
console.log(user);
Output:
{ id: 2, name: 'Priya' }
12.5 reduce()
The reduce() method processes array elements to produce a single accumulated result, such as a sum or total price.
const prices = [100, 200, 300];
const total = prices.reduce((sum, price) => {
return sum + price;
}, 0);
console.log(total);
Output:
600
12.6 Array Methods Comparison
| Method |
Purpose |
Typical Result |
| map() |
Transform each element |
New array |
| filter() |
Select matching elements |
New array |
| forEach() |
Perform an action for each element |
undefined |
| find() |
Find the first matching element |
Element or undefined |
| reduce() |
Accumulate a result |
Single accumulated value |
13. Higher-Order Functions
A higher-order function is a function that accepts another function as an argument, returns a function, or does both. Callback-based functions are often examples of higher-order functions.
13.1 Accepting a Function as an Argument
function performOperation(a, b, operation) {
return operation(a, b);
}
const addition = (a, b) => a + b;
const multiplication = (a, b) => a * b;
console.log(performOperation(4, 3, addition));
console.log(performOperation(4, 3, multiplication));
Output:
7
12
13.2 Returning a Function
function createMultiplier(multiplier) {
return function (number) {
return number * multiplier;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5));
console.log(triple(5));
Output:
10
15
Higher-order functions help separate the operation from the data or context in which it is used.
14. Functions in React Native
React Native applications use functions to define component behavior, respond to user interactions, transform data, and perform application tasks. Functional components are ordinary JavaScript functions that return React elements, commonly written using JSX.
14.1 A Simple Functional Component
import React from "react";
import { View, Text } from "react-native";
export default function WelcomeScreen() {
return (
<View>
<Text>Welcome to React Native!</Text>
</View>
);
}
WelcomeScreen is a function component. When React renders it, the returned JSX describes the interface.
14.2 Using a Helper Function in a Component
import React from "react";
import { View, Text } from "react-native";
function formatWelcome(name) {
return `Welcome, ${name}!`;
}
export default function WelcomeScreen() {
return (
<View>
<Text>{formatWelcome("Aarav")}</Text>
</View>
);
}
The helper function returns text that the component displays inside a Text component.
15. Event Handling and Callback Functions in React Native
React Native components provide event props such as onPress for pressable controls. These props generally expect a function that React Native can call when the event occurs.
15.1 Handling a Button Press
import React from "react";
import { View, Button, Alert } from "react-native";
export default function App() {
function handlePress() {
Alert.alert("Success", "The button was pressed!");
}
return (
<View>
<Button
title="Press Me"
onPress={handlePress}
/>
</View>
);
}
In this example, handlePress is passed as a callback. React Native invokes it when the user presses the button.
15.2 Using an Arrow Function as an Event Handler
import React from "react";
import { View, Button, Alert } from "react-native";
export default function App() {
return (
<View>
<Button
title="Show Message"
onPress={() => Alert.alert("Hello", "Welcome!")}
/>
</View>
);
}
An inline arrow function is useful for a short event handler. For more complex behavior, a separately named function can improve readability.
15.3 Passing Arguments to Event Handlers
If an event handler needs an argument, use a wrapper function so the action runs when the event occurs, rather than immediately during rendering.
import React from "react";
import { View, Button, Alert } from "react-native";
export default function App() {
function showUser(name) {
Alert.alert("Selected User", name);
}
return (
<View>
<Button
title="Select Aarav"
onPress={() => showUser("Aarav")}
/>
<Button
title="Select Priya"
onPress={() => showUser("Priya")}
/>
</View>
);
}
The arrow function acts as a wrapper callback and supplies the selected name when the button is pressed.
15.4 Incorrect Event Handler Assignment
// Incorrect for an event handler:
<Button title="Press Me" onPress={handlePress()} />
// Correct:
<Button title="Press Me" onPress={handlePress} />
// Also correct when arguments are needed:
<Button title="Press Me" onPress={() => handlePress("Aarav")} />
The incorrect example calls handlePress() during rendering and passes its return value instead of passing the function itself. Event handlers should normally receive a function reference.
16. Functions with React State
React's useState hook allows a functional component to store and update state. State setter functions can accept either a new value or an updater callback. An updater callback receives the previous state and calculates the next state.
16.1 Updating a Counter
import React, { useState } from "react";
import { View, Text, Button } from "react-native";
export default function CounterApp() {
const [count, setCount] = useState(0);
function increaseCount() {
setCount(previousCount => previousCount + 1);
}
return (
<View>
<Text>Count: {count}</Text>
<Button title="Increase" onPress={increaseCount} />
</View>
);
}
The callback previousCount => previousCount + 1 calculates the next state from the previous state. This approach is useful when the next value depends on the previous value.
16.2 Decreasing a Counter
function decreaseCount() {
setCount(previousCount => previousCount - 1);
}
For a complete component, define decreaseCount inside the component where setCount is available, and pass it to the appropriate event prop.
16.3 Toggle State
function toggleStatus() {
setIsActive(previousStatus => !previousStatus);
}
This updater callback calculates the next Boolean state from the previous state.
16.4 Avoid Mutating State Directly
// Avoid changing state variables directly.
items.push(newItem);
// Prefer creating a new array.
setItems(previousItems => [...previousItems, newItem]);
When updating arrays or objects in React state, create a new value rather than modifying the existing state value directly.
17. Callback Functions for Lists in React Native
List screens frequently need callbacks to transform, filter, or render data. JavaScript array methods are useful for preparing data, while React Native's FlatList supports efficient rendering of longer lists.
17.1 Rendering a List with map()
import React from "react";
import { View, Text } from "react-native";
export default function NameList() {
const names = ["Aarav", "Priya", "Rohan"];
return (
<View>
{names.map(name => (
<Text key={name}>{name}</Text>
))}
</View>
);
}
The callback passed to map() returns a Text element for each name. Each rendered item should have a stable, unique key. If names are not unique, use a unique identifier from the data.
17.2 Rendering Data with FlatList
import React from "react";
import { FlatList, Text } from "react-native";
const users = [
{ id: "1", name: "Aarav" },
{ id: "2", name: "Priya" },
{ id: "3", name: "Rohan" }
];
export default function UserList() {
return (
<FlatList
data={users}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Text>{item.name}</Text>
)}
/>
);
}
The keyExtractor callback returns a stable key for each item. The renderItem callback describes how each item should appear.
17.3 Filtering List Data
const activeUsers = users.filter(user => user.active);
This expression returns a new array containing only users whose active property is truthy. Ensure that the data objects actually contain the property used in the filter.
18. Asynchronous Functions and Callbacks
React Native applications often need to retrieve information from servers or perform operations that complete later. JavaScript supports callbacks, promises, and async/await for handling asynchronous work.
18.1 Callback with setTimeout()
function showDelayedMessage(callback) {
setTimeout(() => {
callback("Data received!");
}, 1000);
}
showDelayedMessage(message => {
console.log(message);
});
The callback receives the message after the timer completes.
18.2 Using Promises
function fetchMessage() {
return new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("Operation completed");
} else {
reject(new Error("Operation failed"));
}
});
}
fetchMessage()
.then(message => console.log(message))
.catch(error => console.error(error.message));
A promise represents the eventual completion or failure of an asynchronous operation. The then() and catch() methods accept callbacks for handling success and failure.
18.3 Using async and await
async function loadMessage() {
try {
const message = await fetchMessage();
console.log(message);
} catch (error) {
console.error(error.message);
}
}
loadMessage();
The async keyword makes a function return a promise. The await keyword pauses that async function until the awaited promise settles, without blocking the entire JavaScript thread.
18.4 Fetching Data in a React Native App
async function loadUsers() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
if (!response.ok) {
throw new Error("Failed to load users");
}
const users = await response.json();
return users;
} catch (error) {
console.error("Error loading users:", error.message);
throw error;
}
}
This function requests user data, checks the HTTP response status, parses the JSON response, and returns the data. The calling code should handle the returned promise and display loading, success, or error states as appropriate.
19. Common Mistakes When Using Functions and Callbacks
19.1 Calling a Function Instead of Passing It
// Incorrect:
buttonHandler()
// Pass the function reference:
buttonHandler
In event props such as onPress, passing the function reference allows React Native to call it when the event occurs. Calling the function immediately is appropriate only when immediate execution is intended.
19.2 Forgetting to Return a Value
const calculate = (a, b) => {
a + b;
};
console.log(calculate(2, 3)); // undefined
To return the result, use return a + b; inside the block or use the concise expression form const calculate = (a, b) => a + b;.
19.3 Confusing map() and forEach()
const numbers = [1, 2, 3];
const doubled = numbers.map(number => number * 2);
const result = numbers.forEach(number => number * 2);
console.log(doubled); // [2, 4, 6]
console.log(result); // undefined
Use map() when you need a transformed array. Use forEach() when you need to perform an action for each item.
19.4 Using an Arrow Function with the Wrong Return Syntax
// Incorrect if an object is intended:
const createUser = name => { name: name };
// Correct:
const createUser = name => ({ name: name });
Wrap an object literal in parentheses when returning it implicitly from an arrow function.
19.5 Forgetting Error Handling
async function loadData() {
try {
const response = await fetch("https://example.com/data");
if (!response.ok) {
throw new Error("Request failed");
}
return await response.json();
} catch (error) {
console.error(error.message);
throw error;
}
}
In production applications, handle failed requests and show an appropriate message to users rather than relying only on console output.
19.6 Using Stale State in Callbacks
A callback created during a render can capture values from that render. When updating state based on the previous state, use the functional updater form when appropriate.
setCount(previousCount => previousCount + 1);
For effects and long-lived callbacks, review the relevant dependencies and how values are captured. Do not assume every callback automatically receives the latest value of every variable.
20. Best Practices for Functions in React Native
- Use meaningful function names such as
handleSubmit, calculateTotal, and loadUsers.
- Keep functions focused on one clear responsibility.
- Prefer reusable helper functions when the same logic is needed in several places.
- Use arrow functions where their concise syntax and lexical behavior are suitable.
- Use named functions when they improve readability and debugging.
- Pass function references to event props instead of calling handlers during rendering.
- Use wrapper callbacks when an event handler needs specific arguments.
- Return values when the caller needs to use the result.
- Use
map() for transformations and filter() for selection.
- Use functional state updates when the next state depends on the previous state.
- Handle rejected promises and failed HTTP responses.
- Avoid mutating arrays and objects stored in React state.
- Use stable keys when rendering collections of elements.
- Keep inline callbacks simple; extract complicated logic into named functions.
- Use
useCallback only when there is a practical reason to preserve a function reference, such as a memoized child or a dependency requirement. It is not automatically necessary for every handler.
- Test important functions with typical, boundary, and invalid inputs.
21. Practical Exercise 1: Calculator Functions
Objective: Create reusable functions for basic mathematical operations.
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const multiply = (a, b) => a * b;
const divide = (a, b) => {
if (b === 0) {
return "Cannot divide by zero";
}
return a / b;
};
console.log(add(10, 5));
console.log(subtract(10, 5));
console.log(multiply(10, 5));
console.log(divide(10, 5));
console.log(divide(10, 0));
Expected output:
15
5
50
2
Cannot divide by zero
Practice task: Add a function that calculates the remainder and another that calculates a percentage.
22. Practical Exercise 2: Callback-Based Calculator
Objective: Pass a function as an argument to perform different calculations.
function calculate(a, b, callback) {
return callback(a, b);
}
const add = (a, b) => a + b;
const multiply = (a, b) => a * b;
const subtract = (a, b) => a - b;
console.log(calculate(8, 2, add));
console.log(calculate(8, 2, multiply));
console.log(calculate(8, 2, subtract));
Expected output:
10
16
6
Practice task: Add division with validation and pass it as another callback.
23. Practical Exercise 3: React Native Counter App
Objective: Use functions, arrow functions, event callbacks, and state updater callbacks to build a simple counter.
import React, { useState } from "react";
import { View, Text, Button, StyleSheet } from "react-native";
export default function CounterApp() {
const [count, setCount] = useState(0);
const increase = () => {
setCount(previousCount => previousCount + 1);
};
const decrease = () => {
setCount(previousCount => previousCount - 1);
};
const reset = () => {
setCount(0);
};
return (
<View style={styles.container}>
<Text style={styles.title}>Counter App</Text>
<Text style={styles.count}>Count: {count}</Text>
<Button title="Increase" onPress={increase} />
<Button title="Decrease" onPress={decrease} />
<Button title="Reset" onPress={reset} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
padding: 20,
gap: 12
},
title: {
fontSize: 24,
textAlign: "center",
fontWeight: "bold"
},
count: {
fontSize: 20,
textAlign: "center"
}
});
What this project demonstrates:
CounterApp is a functional component.
increase, decrease, and reset are event handler functions.
- The
onPress props receive function references.
- The updater callbacks calculate new values from the previous state.
- The interface updates when the counter state changes.
24. Practical Exercise 4: User List and Filtering
Objective: Use arrow functions, filter(), and map() to display a filtered list.
import React from "react";
import { View, Text } from "react-native";
const users = [
{ id: "1", name: "Aarav", active: true },
{ id: "2", name: "Priya", active: false },
{ id: "3", name: "Rohan", active: true }
];
export default function ActiveUserList() {
const activeUsers = users.filter(user => user.active);
return (
<View>
<Text>Active Users</Text>
{activeUsers.map(user => (
<Text key={user.id}>{user.name}</Text>
))}
</View>
);
}
Expected result: The screen displays Aarav and Rohan because their active property is true.
25. Interview Questions and Answers
Q1. What is a function in JavaScript?
A function is a reusable block of code that performs a task. It can accept input through parameters and optionally return a result.
Q2. What is the difference between a parameter and an argument?
A parameter is a variable listed in a function definition. An argument is a value supplied when the function is called.
Q3. What is an arrow function?
An arrow function is a function expression that uses the => syntax. It provides concise syntax and inherits this from its surrounding lexical scope.
Q4. What is an implicit return?
An implicit return occurs when a concise arrow function returns the result of an expression without using an explicit return statement.
Q5. What is a callback function?
A callback is a function passed to another function so that the receiving function can invoke it at the appropriate time.
Q6. What is a higher-order function?
A higher-order function accepts a function as an argument, returns a function, or both.
Q7. What is the difference between map() and forEach()?
map() creates a new array from callback results. forEach() executes a callback for each element and returns undefined.
Q8. Why do React Native event handlers use callbacks?
Callbacks allow React Native to invoke application logic in response to events, such as a user pressing a button.
Q9. Why should you avoid calling an event handler during rendering?
Calling a handler during rendering executes it immediately rather than waiting for the event. Passing the function reference or using a wrapper callback avoids this problem.
Q10. Can arrow functions be used as constructors?
No. Arrow functions cannot be used with new because they do not have the constructor behavior of ordinary constructible functions.
Q11. What does a function return if there is no return statement?
It returns undefined.
Q12. What is a closure?
A closure is a function that retains access to variables from its surrounding lexical environment, even after the outer function has finished executing.
Q13. What is the purpose of a functional state updater?
A functional state updater receives the previous state and calculates the next state. It is useful when the new state depends on the previous value.
Q14. What is the difference between synchronous and asynchronous callbacks?
A synchronous callback executes during the current operation. An asynchronous callback is scheduled to execute later, such as after a timer or an event.
Q15. When should useCallback be considered in React?
useCallback can preserve a function reference between renders when that is useful for memoized children or hook dependencies. It should be applied when there is a practical benefit, not automatically to every function.
26. Quick Revision Checklist
- Understand function declarations and function expressions.
- Know the difference between parameters and arguments.
- Understand how return statements work.
- Recognize default and rest parameters.
- Create arrow functions with zero, one, or multiple parameters.
- Understand implicit returns and object return syntax.
- Know how traditional functions differ from arrow functions.
- Understand scope, lexical scope, and closures.
- Explain callback functions and higher-order functions.
- Use callbacks with map(), filter(), forEach(), find(), and reduce().
- Pass functions to React Native event props such as onPress.
- Use functional state updates when the next value depends on the previous state.
- Understand basic asynchronous callbacks, promises, and async/await.
- Handle errors and avoid common function-related mistakes.
27. Recommended Learning Resources
28. Conclusion
Functions, arrow functions, and callback functions are fundamental building blocks of JavaScript and React Native development. Functions organize reusable logic, arrow functions offer concise syntax and lexical this behavior, and callbacks allow one function to provide behavior to another.
These concepts are used throughout React Native applications, including button event handlers, state updates, list rendering, data transformations, and asynchronous requests. Practising the examples and exercises in these notes will help learners write cleaner, more reusable, and easier-to-maintain mobile application code.
For more information about React Native training, visit React Native Training at JustAcademy or register through the course demo registration page.